// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef UI_EVENTS_EVENT_TARGET_H_
#define UI_EVENTS_EVENT_TARGET_H_

#include <vector>

#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "ui/events/event_handler.h"
#include "ui/events/events_export.h"

namespace ui {

class EventDispatcher;
class EventTargeter;
class EventTargetIterator;
class LocatedEvent;

class EVENTS_EXPORT EventTarget {
public:
    class DispatcherApi {
    public:
        explicit DispatcherApi(EventTarget* target)
            : target_(target)
        {
        }

        const EventHandlerList& pre_target_list() const
        {
            return target_->pre_target_list_;
        }

    private:
        DispatcherApi();
        EventTarget* target_;

        DISALLOW_COPY_AND_ASSIGN(DispatcherApi);
    };

    EventTarget();
    virtual ~EventTarget();

    virtual bool CanAcceptEvent(const Event& event) = 0;

    // Returns the parent EventTarget in the event-target tree.
    virtual EventTarget* GetParentTarget() = 0;

    // Returns an iterator an EventTargeter can use to iterate over the list of
    // child EventTargets.
    virtual scoped_ptr<EventTargetIterator> GetChildIterator() const = 0;

    // Returns the EventTargeter that should be used to find the target for an
    // event in the subtree rooted at this EventTarget.
    virtual EventTargeter* GetEventTargeter() = 0;

    // Updates the states in |event| (e.g. location) to be suitable for |target|,
    // so that |event| can be dispatched to |target|.
    virtual void ConvertEventToTarget(EventTarget* target,
        LocatedEvent* event);

    // Adds a handler to receive events before the target. The handler must be
    // explicitly removed from the target before the handler is destroyed. The
    // EventTarget does not take ownership of the handler.
    void AddPreTargetHandler(EventHandler* handler);

    // Same as AddPreTargetHandler except that the |handler| is added to the front
    // of the list so it is the first one to receive events.
    void PrependPreTargetHandler(EventHandler* handler);
    void RemovePreTargetHandler(EventHandler* handler);

    // Adds a handler to receive events after the target. The handler must be
    // explicitly removed from the target before the handler is destroyed. The
    // EventTarget does not take ownership of the handler.
    void AddPostTargetHandler(EventHandler* handler);
    void RemovePostTargetHandler(EventHandler* handler);

    // Returns true if the event pre target list is empty.
    bool IsPreTargetListEmpty() const;

    // Sets |target_handler| as |target_handler_| and returns the old handler.
    EventHandler* SetTargetHandler(EventHandler* target_handler);

protected:
    EventHandler* target_handler() { return target_handler_; }

private:
    friend class EventDispatcher;
    friend class EventTargetTestApi;

    // Returns the list of handlers that should receive the event before the
    // target. The handlers from the outermost target are first in the list, and
    // the handlers on |this| are the last in the list.
    void GetPreTargetHandlers(EventHandlerList* list);

    // Returns the list of handlers that should receive the event after the
    // target. The handlers from the outermost target are last in the list, and
    // the handlers on |this| are the first in the list.
    void GetPostTargetHandlers(EventHandlerList* list);

    EventHandlerList pre_target_list_;
    EventHandlerList post_target_list_;
    EventHandler* target_handler_;

    DISALLOW_COPY_AND_ASSIGN(EventTarget);
};

} // namespace ui

#endif // UI_EVENTS_EVENT_TARGET_H_
